package com.ruslan.magaz.repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.ruslan.magaz.domain.Customer;
import com.ruslan.magaz.domain.Order;
import com.ruslan.magaz.domain.OrderStatus;
import com.ruslan.magaz.domain.OrderStatusName;
import com.ruslan.magaz.domain.OrderedItem;
import com.ruslan.magaz.domain.Product;
import com.ruslan.magaz.domain.Role;
import com.ruslan.magaz.domain.User;
import com.ruslan.magaz.service.OrderService;

@Repository
public class OrderDaoImpl implements OrderDao{
	
	public static String ORDERLINES_QUERY = "select oi.order.id, sum(oi.productPrice*oi.productQuantity)*(1-o.discount/100), os.statusTime "
			+ "from OrderedItem oi, Order o, OrderStatus os where o.orderId = oi.order.id and o.orderId = os.order.id "
			+ "	and customer_id = :customerId and orderStatusName_id = :initialStatusId	group by oi.order.id";
	
	@Autowired
	private SessionFactory sessionFactory;
	
	@Override
	public void addOrder(int userId, Order order) {
		Session session = sessionFactory.getCurrentSession();
		session.save(order);
		User existingUser = (User) session.get(User.class, userId);
		existingUser.getCustomer().getOrders().add(order);		
	}


	@Override
	public void removeOrder(Order order) {
		Session session = sessionFactory.getCurrentSession();
		session.delete(order);		
	}

	@Override
	public void editOrder(Order order) {
		Session session = sessionFactory.getCurrentSession();
		Order existingOrder = (Order) session.get(Order.class, order.getOrderId());
		existingOrder.setDiscount(order.getDiscount());
	}

	@Override
	public Order getOrderById(int id) {
		Session session = sessionFactory.getCurrentSession();
		return (Order) session.get(Order.class, id);
	}

	@Override
	public List<Order> getAllOrdersForUser(int userId, int pageNum, int pageSize) {
		Session session = sessionFactory.getCurrentSession();
		User user = (User) session.get(User.class, userId);
		int customerId = user.getCustomer().getCustomerId();
		Query query = session.createQuery("FROM Order where customer_id = :id");
		query.setInteger("id", customerId);
		query.setFirstResult((pageNum - 1) * pageSize);
		query.setMaxResults(pageSize);
		return  (List<Order>) query.list();
	}
	
	@Override
	public List<OrderStatusName> getAllOrderStatusNames() {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("FROM OrderStatusName");
		return  (List<OrderStatusName>) query.list();
	}

	@Override
	public void addOrderedItem(int orderId, OrderedItem orderedItem) {
		Session session = sessionFactory.getCurrentSession();
		session.save(orderedItem);
		Order order = (Order) session.get(Order.class, orderId);
		order.getOrderedItems().add(orderedItem);
		
	}

	@Override
	public void removeOrderedItem(OrderedItem orderItem) {
		Session session = sessionFactory.getCurrentSession();
		session.delete(orderItem);
	}

	@Override
	public void editOrderedItem(OrderedItem orderedItem) {
		Session session = sessionFactory.getCurrentSession();
		OrderedItem existingOrderedItem = (OrderedItem) session.get(OrderedItem.class, orderedItem.getOrderedItemId());
		existingOrderedItem.setProductPrice(orderedItem.getProductPrice());
		existingOrderedItem.setProductQuantity(orderedItem.getProductQuantity());
	}

	@Override
	public OrderedItem getOrderedItemById(int orderedItemId) {
		Session session = sessionFactory.getCurrentSession();
		return (OrderedItem) session.get(Order.class, orderedItemId);
	}

//	@Override
//	public List<OrderedItem> getAllOrderedItemsForOrder(int orderId) {
//		Session session = sessionFactory.getCurrentSession();
//		Query query = session.createQuery("SELECT a FROM OrderedItem a where order_id = :id");
//		query.setInteger("id", orderId);
//		return  (List<OrderedItem>) query.list();
//	}

	@Override
	public void addOrderStatus(int orderId, OrderStatus orderStatus) {
		Session session = sessionFactory.getCurrentSession();
		session.save(orderStatus);
		Order order = (Order) session.get(Order.class, orderId);
		order.getOrderStatuses().add(orderStatus);		
	}

	@Override
	public void removeOrderStatus(OrderStatus orderStatus) {
		Session session = sessionFactory.getCurrentSession();
		session.delete(orderStatus);
	}

	@Override
	public void editOrderStatus(OrderStatus orderStatus) {
		Session session = sessionFactory.getCurrentSession();
		OrderStatus existingOS = (OrderStatus) session.get(OrderStatus.class, orderStatus.getOrderStatusId());
		existingOS.setPlace(orderStatus.getPlace());
		existingOS.setStatusTime(orderStatus.getStatusTime());
		existingOS.setOrderStatusName(orderStatus.getOrderStatusName());
	}

	@Override
	public OrderStatus getOrderStatusById(int id) {
		Session session = sessionFactory.getCurrentSession();
		return (OrderStatus) session.get(OrderStatus.class, id);
	}

	@Override
	public List<OrderStatus> getOrderStatusesForOrder(int orderId) {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("SELECT a FROM OrderStatus a where order_id = :id");
		query.setInteger("id", orderId);
		return  (List<OrderStatus>) query.list();
	}


	@Override
	public OrderStatusName getOrderStatusNameById(int id) {
		return (OrderStatusName) sessionFactory.getCurrentSession().get(OrderStatusName.class, id);
	}




	@Override
	public List<Object[]> getOrderLines(int userId, int pageNum, int pageSize) {
		Session session = sessionFactory.getCurrentSession();
		User user = (User) session.get(User.class, userId);
		int customerId = user.getCustomer().getCustomerId();
		Query query = session.createQuery(ORDERLINES_QUERY);
		query.setInteger("customerId", customerId);
		query.setInteger("initialStatusId", OrderService.INITIAL_STATUS_ID);
		query.setFirstResult((pageNum - 1) * pageSize);
		query.setMaxResults(pageSize);
		return  query.list();
	}
	
	@Override
	public int ordersForUserPageCount(int userId, int pageSize) {
		Session session = sessionFactory.getCurrentSession();
		User user = (User) session.get(User.class, userId);
		int customerId = user.getCustomer().getCustomerId();
		Query query = session.createQuery("Select count (o.orderId) FROM Order o WHERE Customer_id = :id");
		query.setInteger("id", customerId);
		return (((Long)query.uniqueResult()).intValue()/pageSize)+1;
	}

	@Override
	public List<OrderedItem> getOrderedItemsForOrder(int orderId, int pageNum, int pageSize) {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("FROM OrderedItem as oi LEFT JOIN FETCH  oi.product WHERE order_id=:id");
		query.setInteger("id", orderId);
		query.setFirstResult((pageNum - 1) * pageSize);
		query.setMaxResults(pageSize);
		return  query.list();
	}

	@Override
	public int orderedItemsForOrderPageCount(int orderId, int pageSize) {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("Select count (o.orderedItemId) FROM OrderedItem o WHERE Order_id = :id");
		query.setInteger("id", orderId);
		return (((Long)query.uniqueResult()).intValue()/pageSize)+1;
	}
	
	@Override
	public User getUsersforOrder(int orderId) {
		Session session = sessionFactory.getCurrentSession();
		Query query = session.createQuery("Select o.customer.user FROM Order o WHERE Order_id = :id");
		query.setInteger("id", orderId);
		return (User) query.uniqueResult();
	}
}
